package cheme.ProcessModel;

import java.beans.PropertyChangeEvent;
import java.io.IOException;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import org.eclipse.draw2d.geometry.Rectangle;

import cheme.ProcessModel.Annotations.IAnnotation;
import cheme.ProcessModel.Equations.Equation;
import cheme.ProcessModel.Equations.Equations;
import cheme.ProcessModel.ProcessUnits.IProcessUnit;
import cheme.ProcessModel.ProcessUnits.ProcessUnit;
import cheme.ProcessModel.ProcessUnits.Streams.Stream;
import cheme.ProcessModel.ProcessUnits.Streams.Tags.ITagComponent;
import cheme.ProcessModel.ProcessUnits.Streams.Tags.Tag;
import cheme.ProcessModel.Visitors.IModelVisitor;

/*
 * The root element of the chemical process model. This element contains an
 * Equations element initially and may have process units added to it (Streams,
 * in turn, are children of process units only, and Tags are children of
 * Streams. Equations are children of the Equations EquationList element).
 */

public class ProcessModel extends AbstractParent<IChild> implements IProcessModel, /*IEquationParent,*/ Serializable
{
	/*
	 * Serialization version identifier. (Set to default for now)
	 */
	
	private static final long serialVersionUID = 1L;
	
	/*
	 * Default indices of this model element's primary children.
	 */

	public static final int EQUATIONS_INDEX = 0;
	public static final int CONSOLE_VIEW_INDEX = 1;
	public static final int TOOL_TIP_MODEL = 2;
	
	public static final int NEXT_INDEX = 2+1;
	
	// PA experiment -- Contents model
	private static String me = " cheme.ProcessModel.ProcessModel";
	private Rectangle constraint;
	
	/*
	 * Store the degree to which this element presentation is scaled prior to
	 * painting on the canvas.
	 */
	
	private transient double zoom = 1.0;
	
	public double getZoom()
	{
		return zoom;
	}

	public void setZoom(double zoom)
	{
		this.zoom = zoom;
	}
	
	public ProcessModel()
	{
		this(null);
	}
	
	public ProcessModel(IModelElement parent)
	{
		super(null);

		add((Equations)ModelEnv.getInstanceFor(this).createModelElement(ProcessModelConstants.EQUATIONS, this), EQUATIONS_INDEX);
		
				
		add((ConsoleView)ModelEnv.getInstanceFor(this).createModelElement(ProcessModelConstants.CONSOLE_VIEW, this), CONSOLE_VIEW_INDEX);
		add((TooltipModel)ModelEnv.getInstanceFor(this).createModelElement(ProcessModelConstants.TOOLTIPMODEL, this), TOOL_TIP_MODEL);
		
				
		
		ModelEnv.getInstanceFor(getRoot()).hookModelElement(this.getRoot());
	}
	
//	private void writeObject(java.io.ObjectOutputStream out) throws IOException
//	{
//	}
	
	private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException
	{
		zoom = 1.0;
		ModelEnv.getInstanceFor(this).hookModelElement(this);
	}
	
	@Override
	public void addAnnotation(IAnnotation annotation)
	{
		getEquations().addAnnotation(annotation);
	}
	
	@Override
	public void removeAnnotation(IAnnotation annotation)
	{
		getEquations().removeAnnotation(annotation);
	}
	
	/**
	 * @return the equations
	 */
	public Equations getEquations()
	{
		return (Equations)get(EQUATIONS_INDEX);
	}
	
	@Override
	protected void unhookChild(IChild child)
	{
		ModelEnv.getInstanceFor(this).hookModelElement(child);
		super.unhookChild(child);
	}
	
	// JB: Experiment
	public void add(IChild child)
	{
		addInternal(child);
		
		//ChemePropertyChangeEvent evt = 
		//	new ChemePropertyChangeEvent(this, IPropertyAware.P_INTERPRETABLE, null, pu, 
		//								new ChemePropertyChangeEvent(this, IPropertyAware.P_CHILD, null, pu));

		firePropertyChange(IPropertyAware.P_CHILD, null, child);
		//firePropertyChange(IPropertyAware.P_INTERPRETABLE, null, this);
	}
	
	public void remove(IChild child)
	{
		removeInternal(child);		
		firePropertyChange(IPropertyAware.P_CHILD, child, null);
		// PA uncommented this - For stream deletion handling.
		firePropertyChange(IPropertyAware.P_INTERPRETABLE, child, this);
	
	}


	//	 JB: Experiment
	
	public void add(Equation equation)
	{
		 getEquations().add(equation);
	}
	
	public void remove(Equation equation)
	{
		 getEquations().remove(equation);
	}
	
	@Override
	protected String getToStringSeparator()
	{
		return "\n------------------------------------\n";
	}
	
	public Object accept(IModelVisitor modelVisitor)
	{
		return modelVisitor.visit(this);
	}
	
	// PA experiment -- Contents model
	public Rectangle getConstraint()
	{
		//SimpleLogger.log(me + getSet, me + ".getConstraint()");
		
		return constraint;
	}

	public void setConstraint(Rectangle rect)
	{
		String getSet = "-getSet";
		SimpleLogger.log(me + getSet, me + ".setConstraint(rect)");
		
		constraint = rect;
		firePropertyChange(P_CONSTRAINT, null, constraint);
	}
}
